package com.whfc.emp.service.impl;

import com.whfc.common.exception.BizException;
import com.whfc.common.result.ResultEnum;
import com.whfc.emp.dto.ClassMeetingInspectionDTO;
import com.whfc.emp.dto.UnSignedWorkerDTO;
import com.whfc.emp.dto.SupervisorDTO;
import com.whfc.emp.entity.AppEmp;
import com.whfc.emp.service.ClassMeetingInspectionService;
import com.whfc.emp.service.ClassMeetingService;
import com.whfc.emp.service.ClassMeetingSignService;
import com.whfc.emp.service.AppWorkPlanService;
import com.whfc.emp.service.AppEmpService;
import com.whfc.emp.entity.ClassMeeting;
import com.whfc.emp.entity.ClassMeetingSign;
import com.whfc.emp.entity.AppWorkPlan;
import com.whfc.entity.dto.Apply.rep.ClassMeetingInfoRep;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 班会签到巡检服务实现
 * @Author dzg
 * @Date 2025-11-10
 * @Version 1.0
 */
@Slf4j
@DubboService(interfaceClass = ClassMeetingInspectionService.class, version = "1.0.0", timeout = 30000)
public class ClassMeetingInspectionServiceImpl implements ClassMeetingInspectionService {

    @Autowired
    private ClassMeetingService classMeetingService;

    @Autowired
    private ClassMeetingSignService classMeetingSignService;

    @Autowired
    private AppWorkPlanService appWorkPlanService;

    @Autowired
    private AppEmpService appEmpService;

    @Override
    public void executeInspection() throws BizException {
        log.info("开始执行班会签到巡检任务");

        // 1. 获取当天已开始或结束的班会列表
        List<ClassMeeting> meetings = getTodayMeetings();
        if (CollectionUtils.isEmpty(meetings)) {
            log.info("当天没有需要巡检的班会");
            return;
        }

        // 2. 对每个班会进行巡检
        for (ClassMeeting meeting : meetings) {
            try {
                executeInspectionByMeetingId(meeting.getId());
            } catch (Exception e) {
                log.error("巡检班会ID: {} 时发生异常", meeting.getId(), e);
            }
        }

        log.info("班会签到巡检任务执行完成，共巡检 {} 个班会", meetings.size());
    }

    @Override
    public void executeInspectionByMeetingId(Integer meetingId) throws BizException {
        log.info("开始巡检班会ID: {}", meetingId);

        // 1. 获取班会信息
        ClassMeeting meeting = classMeetingService.selectByPrimaryKey(meetingId);
        if (meeting == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "班会不存在，ID: " + meetingId);
        }

        // 2. 获取工作计划信息
        AppWorkPlan workPlan = appWorkPlanService.selectById(meeting.getPlanId());
        if (workPlan == null) {
            log.warn("工作计划不存在，计划ID: {}", meeting.getPlanId());
            return;
        }

        // 3. 获取施工人员列表
//        List<AppEmp> appEmps = appWorkPlanService.getWorkers(workPlan.getId());
//        if (appEmps == null || appEmps.isEmpty()){
//            throw new BizException(ResultEnum.FAILURE.getCode(), "查询班会所属工作计划施工人员失败");
//        }
        List<Integer> workerIds = parseConstructionWorkerIds(workPlan);
        if (CollectionUtils.isEmpty(workerIds)) {
            log.info("工作计划ID: {} 没有施工人员，无需巡检", workPlan.getId());
            return;
        }

        // 4. 获取已签到人员列表
        List<ClassMeetingSign> signedRecords = classMeetingSignService.selectSignByMeetingId(meetingId);
        List<Integer> signedWorkerIds = signedRecords.stream().filter(s -> s.getSignStatus() == 1)
                .map(ClassMeetingSign::getUserId)
                .collect(Collectors.toList());

        // 5. 计算未签到人员
        List<Integer> unsignedWorkerIds = workerIds.stream()
                .filter(workerId -> !signedWorkerIds.contains(workerId))
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(unsignedWorkerIds)) {
            log.info("班会ID: {} 所有施工人员均已签到，无需发送提醒", meetingId);
            return;
        }

        // 7. 发送提醒消息给监护人员
        sendInspectionAlert(meeting, workPlan);

        log.info("班会ID: {} 巡检完成，发现 {} 名未签到人员，已通知监护人员",
                meetingId, unsignedWorkerIds.size());
    }

    /**
     * 获取当天已开始或结束的班会列表
     */
    private List<ClassMeeting> getTodayMeetings() {
        LocalDateTime todayStart = LocalDateTime.now().with(LocalTime.MIN);
        LocalDateTime todayEnd = LocalDateTime.now().with(LocalTime.MAX);
        
        try {
            // 由于ClassMeetingService没有直接的时间范围查询方法，我们可以通过以下方式实现：
            // 1. 查询所有类型的班会（班前会、班后会等）
            List<ClassMeeting> todayMeetings = new ArrayList<>();
            
            // 查询班前会（类型1）
            List<ClassMeeting> morningMeetings = classMeetingService.selectByMeetingType(1);
            if (!CollectionUtils.isEmpty(morningMeetings)) {
                todayMeetings.addAll(filterTodayMeetings(morningMeetings, todayStart, todayEnd));
            }
            
            // 查询班后会（类型2）
            List<ClassMeeting> eveningMeetings = classMeetingService.selectByMeetingType(2);
            if (!CollectionUtils.isEmpty(eveningMeetings)) {
                todayMeetings.addAll(filterTodayMeetings(eveningMeetings, todayStart, todayEnd));
            }
            
            // 可以继续添加其他类型的班会查询
            
            log.info("获取到当天班会列表，共 {} 个班会", todayMeetings.size());
            return todayMeetings;
            
        } catch (Exception e) {
            log.error("查询当天班会列表时发生异常", e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 过滤当天班会（辅助方法）
     */
    private List<ClassMeeting> filterTodayMeetings(List<ClassMeeting> meetings, LocalDateTime todayStart, LocalDateTime todayEnd) {
        return meetings.stream()
                .filter(meeting -> {
                    if (meeting.getStartTime() != null) {
                        try {
                            // 移除毫秒部分后再解析
                            String timeWithoutMillis = meeting.getStartTime().split("\\.")[0];
                            LocalDateTime startTime = LocalDateTime.parse(
                                    timeWithoutMillis,
                                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                            );
                            return !startTime.isBefore(todayStart) && !startTime.isAfter(todayEnd);
                        } catch (Exception e) {
                            log.warn("解析班会开始时间失败，班会ID: {}, 时间: {}", meeting.getId(), meeting.getStartTime());
                            return false;
                        }
                    }
                    return false;
                })
                .collect(Collectors.toList());
    }

    /**
     * 从工作计划中解析施工人员ID列表
     */
    private List<Integer> parseConstructionWorkerIds(AppWorkPlan workPlan) {
        List<Integer> workerIds = new ArrayList<>();

        if (workPlan.getConstructionWorkers() != null && !Objects.equals(workPlan.getConstructionWorkers(), "")) {
            if (!workPlan.getConstructionWorkers().contains(",")) {
                workerIds.add(Integer.valueOf(workPlan.getConstructionWorkers()));
            } else {
                workerIds.add(Integer.valueOf(Arrays.toString(workPlan.getConstructionWorkers().split(","))));
            }
        }

        return workerIds;
    }

    /**
     * 发送巡检提醒消息给监护人员
     */
    private void sendInspectionAlert(ClassMeeting meeting, AppWorkPlan workPlan) {
        // 构建提醒消息内容
        String title = "班会签到人员巡检报警";
        String message = String.format("班会签到巡检提醒：\n" +
                "班会名称：%s， 工作计划：%s， 有未认证签到人员，请及时查看。",
                meeting.getMeetingName(), workPlan.getPlanName());
//        appWorkPlanService.sendAlarmMessageToWorkPlanGuardians(title, message, workPlan.getId());
        classMeetingService.sendAlarmMessageToWorkPlanGuardians(title, message, meeting.getId());
        log.info("发送班会签到巡检提醒：{}", message);
    }
}